package com.jiao.datasource.proxy;

import com.jiao.comm.utils.LogUtil;
import com.jiao.datasource.track.RecordSQLDetail;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;


/**
 * 代理 PreparedStatement.
 * @Author: vincent.jiao
 * @Date: 2021/5/4
 */
public class PreparedStatementProxy extends StatementProxy implements InvocationHandler {
    public PreparedStatementProxy (Statement ps, String sql){
        super(ps);
        super.ps = ps;

        try {
            if(ps != null){
                super.conn = ps.getConnection();
            }

            RecordSQLDetail.recordSql(ps, sql);         //记录sql
        } catch (SQLException e) {
            LogUtil.error(e.getMessage(), e);
        }
    }

    /**
     * 监听方法.
     * setBoolean(int var1, boolean var2) throws SQLException;
     * setByte(int var1, byte var2) throws SQLException;
     * setShort(int var1, short var2) throws SQLException;
     * setInt(int var1, int var2) throws SQLException;
     * setLong(int var1, long var2) throws SQLException;
     * setFloat(int var1, float var2) throws SQLException;
     * setDouble(int var1, double var2) throws SQLException;
     * setBigDecimal(int var1, BigDecimal var2) throws SQLException;
     * setString(int var1, String var2) throws SQLException;
     * setBytes(int var1, byte[] var2) throws SQLException;
     * setDate(int var1, Date var2) throws SQLException;
     * setTime(int var1, Time var2) throws SQLException;
     * setTimestamp(int var1, Timestamp var2) throws SQLException;
     * setObject(int var1, Object var2, int var3) throws SQLException;
     * setObject(int var1, Object var2) throws SQLException;
     * setBlob(int var1, Blob var2) throws SQLException;
     * setClob(int var1, Clob var2) throws SQLException;
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        boolean isExecInvoke = true;
        boolean isExecListener = false;
        Object value = null;

        try {
            switch (methodName){
                case "addBatch" :
                    isExecListener = false;
                    batch(proxy, method, args);
                    break;

                case "executeBatch" :
                    isExecListener = true;
                    batch(proxy, method, args);
                    break;

                case "executeUpdate" :
                    isExecInvoke = false;
                    isExecListener = true;
                    value = executeUpdate(proxy, method, args);
                    break;

                case "executeQuery" :
                    isExecListener = true;
                    executeQuery(proxy,method, args);
                    break;

                case "execute" :
                    isExecInvoke = false;
                    isExecListener = true;
                    value = execute(proxy, method, args);
                    break;
                case "setBoolean" :
                case "setByte" :
                case "setShort" :
                case "setInt" :
                case "setLong" :
                case "setFloat" :
                case "setDouble" :
                case "setBigDecimal" :
                case "setString" :
                case "setBytes" :
                case "setDate" :
                case "setTime" :
                case "setTimestamp" :
                case "setObject" :
                case "setBlob" :
                case "setClob" :
                    RecordSQLDetail.recordParam((Integer) args[0], args[1]);
                    break;
            }

            if(isExecInvoke){
                value = execInvoke(proxy, method, args, isExecListener);
            }

        } catch (Exception e){
            throw e;
        }

        return value;
    }
}

